package com.shadowtorcher.soulknife;
/*
 * Copyright (C)  li, Shadow Torcher project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import com.shadowtorcher.soulknife.crud.Inserter;
import com.shadowtorcher.soulknife.exception.BeanConfigErrorException;
import com.shadowtorcher.soulknife.tableManager.Manager;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Map;
import java.util.TreeMap;


public class DataSupport {

    public DataSupport() {
        try {
            Manager.init(this.getClass());
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }

    public static Map<String, Object> getNotNullMember(DataSupport object) throws BeanConfigErrorException {
        Map<String, Object> notNullMember = new TreeMap<>();
        // Map<MemberName,MemberVal>
        try {

            for (Field aField : object.getClass().getDeclaredFields()) {
                String name = aField.getName();
                Method method = object.getClass().getMethod("get" + name);
                Object val = method.invoke(object);
                if (val != null) {
                    notNullMember.put(name, val);
                }
            }
        } catch (Exception e) {
            BeanConfigErrorException beanConfigErrorException;
            beanConfigErrorException = new BeanConfigErrorException(e, e.toString());
            throw beanConfigErrorException;

        }
        return notNullMember;
    }

    /**
     * Get DataSupport class from on resultSet
     *
     * @param resultSet one line of resultSet
     * @param object    subclass.class from DataSupport
     * @return DataSupport class
     */
    protected static DataSupport getInstance(ResultSet resultSet, Class<? extends DataSupport> object)
            throws BeanConfigErrorException, SQLException {
        try {
            DataSupport dataSupport = object.newInstance();
            for (Field aField : object.getDeclaredFields()) {
                String name = aField.getName();
                Method method = object.getMethod("set" + name, aField.getType());
                String type = aField.getGenericType().toString();
                switch (type) {
                    // TODO add more type
                    case "class java.lang.String":
                        method.invoke(dataSupport, resultSet.getString(name));
                        break;
                    case "class java.lang.Double":
                    case "double":
                        method.invoke(dataSupport, resultSet.getDouble(name));
                        break;
                    case "class java.lang.Long":
                    case "long":
                        method.invoke(dataSupport, resultSet.getLong(name));
                        break;
                    case "int":
                    case "class java.lang.Integer":
                        method.invoke(dataSupport, resultSet.getInt(name));
                        break;
                    case "class java.lang.Boolean":
                    case "boolean":
                        method.invoke(dataSupport, resultSet.getBoolean(name));
                        break;
                    case "class java.util.Date":
                        method.invoke(dataSupport, resultSet.getDate(name));
                        break;
                }

            }
            return dataSupport;
        } catch (SQLException e) {
            com.shadowtorcher.soulknife.exception.SQLException sqlException;
            sqlException = new com.shadowtorcher.soulknife.exception.SQLException(e);
            throw sqlException;
        } catch (Exception e) {
            BeanConfigErrorException beanConfigErrorException;
            beanConfigErrorException = new BeanConfigErrorException(e);
            throw beanConfigErrorException;
        }
    }

    public void save()
            throws BeanConfigErrorException, SQLException {
        String tableName = this.getClass().getSimpleName();
        Map<String, Object> map = new TreeMap<>();
//         Map<val,data>
        for (Field aField : this.getClass().getDeclaredFields()) {
            String name = aField.getName();
            try {
                Method getMethod = this.getClass().getMethod("get" + name);
                Object data = getMethod.invoke(this);
                map.put(name, data);

//              TODO clear data // Can not do that?
//              Method setMethod = this.getClass().getMethod("set" + name, new Class[]{aField.getType()});
//              setMethod.invoke(this, new Object[]{null});
            } catch (Exception e) {
                BeanConfigErrorException beanConfigErrorException;
                beanConfigErrorException = new BeanConfigErrorException(e);
                throw beanConfigErrorException;
            }
        }
        Inserter.doInsert(tableName, map);
    }


    public void update() {
        // TODO 用 DataSupport 的 PRIMARY_KEY 来更新
    }

    public void delete() {

    }

}
